<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport"
          content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="msapplication-config" content="browserconfig.xml" />
    <title>Walk-through with Terraform Amazon Provider</title>
    <link rel="apple-touch-icon" sizes="180x180" href="/kitchen-terraform/apple-touch-icon-180x180-precomposed.png">
    <link rel="apple-touch-icon" sizes="152x152" href="/kitchen-terraform/apple-touch-icon-152x152-precomposed.png">
    <link rel="apple-touch-icon" sizes="144x144" href="/kitchen-terraform/apple-touch-icon-144x144-precomposed.png">
    <link rel="apple-touch-icon" sizes="114x114" href="/kitchen-terraform/apple-touch-icon-114x114-precomposed.png">
    <link rel="apple-touch-icon" sizes="72x72" href="/kitchen-terraform/apple-touch-icon-72x72-precomposed.png">
    <link rel="apple-touch-icon" href="/kitchen-terraform/apple-touch-icon-precomposed.png">
    <link rel="icon" type="image/png" sizes="196x196" href="/kitchen-terraform/favicon-196x196.png">
    <link rel="icon" type="image/png" sizes="160x160" href="/kitchen-terraform/favicon-160x160.png">
    <link rel="icon" type="image/png" sizes="96x96" href="/kitchen-terraform/favicon-96x96.png">
    <link rel="icon" type="image/png" sizes="32x32" href="/kitchen-terraform/favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="/kitchen-terraform/favicon-16x16.png">
    <link rel="shortcut icon" href="/kitchen-terraform/favicon.png">
    <link rel="icon" type="image/ico" href="/kitchen-terraform/favicon.ico">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
    <link href="/kitchen-terraform/stylesheets/highlighting.css" rel="stylesheet" />
    <link href="/kitchen-terraform/stylesheets/material.css" rel="stylesheet" />
    <link href="/kitchen-terraform/stylesheets/site.css" rel="stylesheet" />
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>
    <script src="/kitchen-terraform/javascripts/site.js"></script>
  </head>
  <body>
    <nav class="navbar fixed-top navbar-expand-lg navbar-light header">
      <img src="/kitchen-terraform/images/kitchen_terraform_logo.png" class="d-inline-block" style="vertical-align: sub; margin-left: 10px;" width="18" height="18" alt="Kitchen-Terraform logo" />
      <a href="/kitchen-terraform/" class="navbar-brand" style="padding-left: 5px;">Kitchen-Terraform</a>
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarNav">
        <ul class="navbar-nav mr-auto">
          <li class="nav-item">
            <a href="/kitchen-terraform/getting_started.html" class="nav-link">Getting Started</a>
          </li>
          <li class="nav-item">
            <a href="/kitchen-terraform/tutorials/" class="nav-link">Tutorials</a>
          </li>
          <li class="nav-item">
            <a href="/kitchen-terraform/about.html" class="nav-link">About</a>
          </li>
          <li class="nav-item">
            <a href="/kitchen-terraform/community/" class="nav-link">Community</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="https://github.com/newcontext-oss/kitchen-terraform">
              <img src="/kitchen-terraform/images/github.png" class="d-inline-block" style="vertical-align: sub;" width="18" height="18" alt="GitHub logo" /> Contribute
            </a>
          </li>
        </ul>
      </div>
    </nav>
    <div class="content text-left">
      <div class="container" style="padding-top: 0px;">
  <div class="row">
    <div class="col-12">
      <div class="jumbotron">
        <h1 class="display-3">
          Terraform Amazon Provider
        </h1>
        <p class="lead">
          Hello! This tutorial will walk you through setting up a Terraform config to spin up an Amazon Web Services (AWS) EC2 instance using Inspec and Kitchen-Terraform from scratch.
          <br><br>
          (Note: these instructions are for Unix based systems only)
        </p>
        <div class="float-right">Author: Nell Shamrell-Harrington</div>
      </div>
    </div>
  </div>
  <div class="row">
    <div class="col-4">
      <div class="list-group" id="list-tab" role="tablist">
        <a class="list-group-item list-group-item-action active" id="list-one-list" data-toggle="list" href="#list-one" role="tab" aria-controls="one">
          1. Prerequisites
        </a>
        <a class="list-group-item list-group-item-action" id="list-two-list" data-toggle="list" href="#list-two" role="tab" aria-controls="two">
          2. Setup development environment
        </a>
        <a class="list-group-item list-group-item-action" id="list-three-list" data-toggle="list" href="#list-three" role="tab" aria-controls="three">
          3. Setup Test Kitchen
        </a>
        <a class="list-group-item list-group-item-action" id="list-four-list" data-toggle="list" href="#list-four" role="tab" aria-controls="four">
          4. Writing a test
        </a>
      </div>
    </div>
    <div class="col-8">
      <div class="tab-content" id="nav-tabContent">
        <div class="tab-pane fade show active" id="list-one" role="tabpanel" aria-labelledby="list-one-list">
          Make sure you have the following prerequisites for this tutorial
          <br><br>
          An AWS Account<br>
          An AWS Access Key ID<br>
          An AWS Secret Key<br>
          An AWS Keypair<br>
          Terraform installed<br>
          Bundler installed<br>
          Ruby >= 2.4, < 2.8<br>
          The default security group on your account must allow SSH access from your IP address.
          <br><br>
          So let's start building this config from scratch!
        </div>
        <div class="tab-pane fade" id="list-two" role="tabpanel" aria-labelledby="list-two-list">
          First, let's create a new directory for our config:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code><span class="nb">mkdir </span>tf_aws_cluster
<span class="nb">cd </span>tf_aws_cluster
</code></pre></div>          Now, create some skeleton terraform files:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code><span class="nb">touch </span>main.tf variables.tf output.tf testing.tfvars
</code></pre></div>          Edit the <p class="font-weight-bold" style="color: #32c850; display: inline;">Gemfile</p>
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>vim Gemfile
</code></pre></div>          Add in the Kitchen-Terraform gem like below (substituting your Ruby version if necessary):
          <br><br>
<div class="highlight"><pre class="syntax-highlight ruby"><code><span class="n">ruby</span> <span class="s1">'&gt;= 3.0'</span>

<span class="n">source</span> <span class="s1">'https://rubygems.org/'</span> <span class="k">do</span>
  <span class="n">gem</span> <span class="s1">'kitchen-terraform'</span><span class="p">,</span> <span class="s1">'~&gt; 7.0'</span>
<span class="k">end</span>
</code></pre></div>          Close and save the file then run bundler to install these gems:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>bundle <span class="nb">install</span>
</code></pre></div>        </div>
        <div class="tab-pane fade" id="list-three" role="tabpanel" aria-labelledby="list-three-list">
          Now let's set up Test Kitchen.
          <br><br>
          Go ahead and open your <p class="font-weight-bold" style="color: #32c850; display: inline;">.kitchen.yml</p> file:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>vim .kitchen.yml
</code></pre></div>          Let's go ahead and add in configuration for for both Test-Kitchen and Kitchen-Terraform in the <p class="font-weight-bold" style="color: #32c850; display: inline;">.kitchen.yml</p> config file.
          <br><br>
          Kitchen-Terraform provides three plugins for use with Test-Kitchen - a driver, a provisioner, and a verifier. We will go through each of these plugins in this tutorial.
          <br><br>
          First the driver - the driver we are using is called terraform.
          <br><br>
          Edit the <p class="font-weight-bold" style="color: #32c850; display: inline;">.kitchen.yml</p> file:
          <br><br>
<div class="highlight"><pre class="syntax-highlight yaml"><code><span class="nn">---</span>
<span class="na">driver</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>
  <span class="na">variable_files</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="s">testing.tfvars</span>
</code></pre></div>          Now let's add the provisioner. The provisioner we will use is also called terraform.
          <br><br>
<div class="highlight"><pre class="syntax-highlight yaml"><code><span class="nn">---</span>
<span class="na">driver</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>
  <span class="na">variable_files</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="s">testing.tfvars</span>

<span class="na">provisioner</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>
</code></pre></div>          Now, we need to add in a platform. Although our terraform config will determine what OS we use, we need to include at least one value here.
          <br><br>
<div class="highlight"><pre class="syntax-highlight yaml"><code><span class="nn">---</span>
<span class="na">driver</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>
  <span class="na">variable_files</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="s">testing.tfvars</span>

<span class="na">provisioner</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>

<span class="na">platforms</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">ubuntu</span>
</code></pre></div>          And now let's add another section, the verifier section. The verifier is what will verify whether your Test Kitchen instances match what is laid out in your inspec files.
          <br><br>
<div class="highlight"><pre class="syntax-highlight yaml"><code><span class="nn">---</span>
<span class="na">driver</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>
  <span class="na">variable_files</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="s">testing.tfvars</span>

<span class="na">provisioner</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>

<span class="na">platforms</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">ubuntu</span>

<span class="na">verifier</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>
  <span class="na">systems</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">default</span>
      <span class="na">controls</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">operating_system</span>
      <span class="na">backend</span><span class="pi">:</span> <span class="s">ssh</span>
      <span class="na">user</span><span class="pi">:</span> <span class="s">ubuntu</span>
      <span class="na">key_files</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">~/path/to/your/private/aws/key.pem</span>
      <span class="na">hosts_output</span><span class="pi">:</span> <span class="s">public_dns</span>
      <span class="na">reporter</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">documentation</span>
</code></pre></div>          And let's stop and talk about what we did here - as this is where you will see some of the uniqueness of Kitchen-Terraform.
          <br><br>
          With these lines:
          <br><br>
<div class="highlight"><pre class="syntax-highlight yaml"><code><span class="na">verifier</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>
</code></pre></div>          We have specified that we are using the terraform verifier.
          <br><br>
          And we have also specified a group of controls:
          <br><br>
<div class="highlight"><pre class="syntax-highlight yaml"><code><span class="na">systems</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">default</span>
    <span class="na">controls</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">operating_system</span>
</code></pre></div>          Our system's name is default, and we expect to find a control file called <p class="font-weight-bold" style="color: #32c850; display: inline;">operating_system_spec.rb</p> within that group.
          <br><br>
          Additionally, we have specified the ssh backend. We would like Kitchen-Terraform to ssh into an instance and run the Inspec tests there:
          <br><br>
<div class="highlight"><pre class="syntax-highlight yaml"><code>      <span class="na">backend</span><span class="pi">:</span> <span class="s">ssh</span>
      <span class="na">user</span><span class="pi">:</span> <span class="s">ubuntu</span>
      <span class="na">key_files</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">~/path/to/your/private/aws/key.pem</span>
      <span class="na">hosts_output</span><span class="pi">:</span> <span class="s">public_dns</span>
      <span class="na">reporter</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">documentation</span>
</code></pre></div>          Kitchen-Terraform also needs to know a username, private keys, and hostnames to ssh run those specs. We have set the hosts_output key to public_dns - which is an output value we will need to add to <p class="font-weight-bold" style="color: #32c850; display: inline;">output.tf</p> in a bit. The user key specifies the username that kitchen terraform will use to ssh into the hostnames with. In this tutorial we are using Ubuntu instances and the default username is ubuntu. Finally the reporter key specifies the InSpec reporters for reporting test output. In this example, we are specifying documentation which shows the tests passed with a small summary at the end.
          <br><br>
          And, last, let's add a test suite to the <p class="font-weight-bold" style="color: #32c850; display: inline;">.kitchen.yml</p> file:
          <br><br>
<div class="highlight"><pre class="syntax-highlight yaml"><code><span class="nn">---</span>
<span class="na">driver</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>
  <span class="na">variable_files</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="s">testing.tfvars</span>

<span class="na">provisioner</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>

<span class="na">platforms</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">ubuntu</span>

<span class="na">verifier</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>
  <span class="na">systems</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">default</span>
      <span class="na">controls</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">operating_system</span>
      <span class="na">backend</span><span class="pi">:</span> <span class="s">ssh</span>
      <span class="na">user</span><span class="pi">:</span> <span class="s">ubuntu</span>
      <span class="na">key_files</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">~/path/to/your/private/aws/key.pem</span>
      <span class="na">hosts_output</span><span class="pi">:</span> <span class="s">public_dns</span>
      <span class="na">reporter</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">documentation</span>

<span class="na">suites</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">default</span>
</code></pre></div>          Save and close the file.
        </div>
        <div class="tab-pane fade" id="list-four" role="tabpanel" aria-labelledby="list-four-list">
          Now, we have some work to do on our workstation. First, let's set up an inspec directory within our test directories
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code><span class="nb">mkdir</span> <span class="nt">-p</span> <span class="nb">test</span>/integration/default/controls
</code></pre></div>          This will be our default group of tests. Now we need to provide a yml file with the name of that group within the group directory. Go ahead and create this:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>vim <span class="nb">test</span>/integration/default/inspec.yml
</code></pre></div>          And add this content:
          <br><br>
<div class="highlight"><pre class="syntax-highlight yaml"><code><span class="nn">---</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">default</span>
</code></pre></div>          Save and close the file.
          <br><br>
          Now, just one more bit of housekeeping. Our <p class="font-weight-bold" style="color: #32c850; display: inline;">.kitchen.yml</p> is expecting an output of our test kitchen instances' hostnames within the output variable, public_dns. In order to have a hostname within that public_dns variable, we need to create an EC2 instance.
          <br><br>
          First, open up the main config file:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>vim main.tf
</code></pre></div>          And add this content:
          Terraform 0.10, 0.11
          <br><br>
<div class="highlight"><pre class="syntax-highlight ruby"><code><span class="n">provider</span> <span class="s2">"aws"</span> <span class="p">{</span>
  <span class="n">access_key</span> <span class="o">=</span> <span class="s2">"${var.access_key}"</span>
  <span class="n">secret_key</span> <span class="o">=</span> <span class="s2">"${var.secret_key}"</span>
  <span class="n">region</span> <span class="o">=</span> <span class="s2">"${var.region}"</span>
<span class="p">}</span>

<span class="n">resource</span> <span class="s2">"aws_security_group"</span> <span class="s2">"allow_ssh"</span> <span class="p">{</span>
  <span class="nb">name</span>        <span class="o">=</span> <span class="s2">"allow_ssh"</span>
  <span class="n">description</span> <span class="o">=</span> <span class="s2">"Allow SSH inbound traffic"</span>

  <span class="n">ingress</span> <span class="p">{</span>
    <span class="n">from_port</span>   <span class="o">=</span> <span class="mi">22</span>
    <span class="n">to_port</span>     <span class="o">=</span> <span class="mi">22</span>
    <span class="n">protocol</span>    <span class="o">=</span> <span class="s2">"tcp"</span>
    <span class="n">cidr_blocks</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"0.0.0.0/0"</span><span class="p">]</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="n">resource</span> <span class="s2">"aws_instance"</span> <span class="s2">"example"</span> <span class="p">{</span>
  <span class="n">ami</span> <span class="o">=</span> <span class="s2">"${var.ami}"</span>
  <span class="n">instance_type</span> <span class="o">=</span> <span class="s2">"${var.instance_type}"</span>
  <span class="n">key_name</span> <span class="o">=</span> <span class="s2">"${var.key_name}"</span>
  <span class="n">security_groups</span> <span class="o">=</span> <span class="s2">"${aws_security_group.allow_ssh.name]"</span>
<span class="p">}</span>
</code></pre></div>          Terraform 0.12
          <br><br>
<div class="highlight"><pre class="syntax-highlight ruby"><code><span class="n">provider</span> <span class="s2">"aws"</span> <span class="p">{</span>
  <span class="n">access_key</span> <span class="o">=</span> <span class="n">var</span><span class="p">.</span><span class="nf">access_key</span>
  <span class="n">secret_key</span> <span class="o">=</span> <span class="n">var</span><span class="p">.</span><span class="nf">secret_key</span>
  <span class="n">region</span>     <span class="o">=</span> <span class="n">var</span><span class="p">.</span><span class="nf">region</span>
<span class="p">}</span>

<span class="n">resource</span> <span class="s2">"aws_security_group"</span> <span class="s2">"allow_ssh"</span> <span class="p">{</span>
  <span class="nb">name</span>        <span class="o">=</span> <span class="s2">"allow_ssh"</span>
  <span class="n">description</span> <span class="o">=</span> <span class="s2">"Allow SSH inbound traffic"</span>

  <span class="n">ingress</span> <span class="p">{</span>
    <span class="n">from_port</span>   <span class="o">=</span> <span class="mi">22</span>
    <span class="n">to_port</span>     <span class="o">=</span> <span class="mi">22</span>
    <span class="n">protocol</span>    <span class="o">=</span> <span class="s2">"tcp"</span>
    <span class="n">cidr_blocks</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"0.0.0.0/0"</span><span class="p">]</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="n">resource</span> <span class="s2">"aws_instance"</span> <span class="s2">"example"</span> <span class="p">{</span>
  <span class="n">ami</span>             <span class="o">=</span> <span class="n">var</span><span class="p">.</span><span class="nf">ami</span>
  <span class="n">instance_type</span>   <span class="o">=</span> <span class="n">var</span><span class="p">.</span><span class="nf">instance_type</span>
  <span class="n">key_name</span>        <span class="o">=</span> <span class="n">var</span><span class="p">.</span><span class="nf">key_name</span>
  <span class="n">security_groups</span> <span class="o">=</span> <span class="p">[</span><span class="n">aws_security_group</span><span class="p">.</span><span class="nf">allow_ssh</span><span class="p">.</span><span class="nf">name</span><span class="p">]</span>
<span class="p">}</span>
</code></pre></div>          Save and close the file. Notice that we used some variable values there? We need to add these into our <p class="font-weight-bold" style="color: #32c850; display: inline;">variables.tf</p> file.
          <br><br>
          Go ahead and create it.
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>vim variables.tf
</code></pre></div>          And add this content:
          <br><br>
<div class="highlight"><pre class="syntax-highlight ruby"><code><span class="n">variable</span> <span class="s2">"access_key"</span> <span class="p">{}</span>
<span class="n">variable</span> <span class="s2">"secret_key"</span> <span class="p">{}</span>
<span class="n">variable</span> <span class="s2">"key_name"</span> <span class="p">{}</span>
<span class="n">variable</span> <span class="s2">"region"</span> <span class="p">{}</span>
<span class="n">variable</span> <span class="s2">"ami"</span> <span class="p">{}</span>
<span class="n">variable</span> <span class="s2">"instance_type"</span> <span class="p">{}</span>
</code></pre></div>          And, finally, we need to add in some values for these variables.
          <br><br>
          Open up your <p class="font-weight-bold" style="color: #32c850; display: inline;">testing.tfvars</p> file:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>vim testing.tfvars
</code></pre></div>          And add in this content (substitute in the appropriate values for your AWS account, region, etc. key_name will be the existing key pair name already existing in AWS)
          <br><br>
<div class="highlight"><pre class="syntax-highlight ruby"><code><span class="n">access_key</span> <span class="o">=</span> <span class="s2">"my_aws_access_key"</span>
<span class="n">secret_key</span> <span class="o">=</span> <span class="s2">"my_aws_secret_key"</span>
<span class="n">key_name</span> <span class="o">=</span> <span class="s2">"my_aws_key_pair_name"</span>
<span class="n">region</span> <span class="o">=</span> <span class="s2">"us-east-1"</span>
<span class="n">ami</span> <span class="o">=</span> <span class="s2">"ami-fce3c696"</span>
<span class="n">instance_type</span> <span class="o">=</span> <span class="s2">"m3.medium"</span>
</code></pre></div>          Save and close the file.
          <br><br>
          Finally, let's define that output that will be expected by our <p class="font-weight-bold" style="color: #32c850; display: inline;">.kitchen.yml</p>
          <br><br>
          Go ahead and open up your <p class="font-weight-bold" style="color: #32c850; display: inline;">output.tf</p> file.
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>vim output.tf
</code></pre></div>          And add this content:
          <br><br>
<div class="highlight"><pre class="syntax-highlight ruby"><code><span class="n">output</span> <span class="s2">"public_dns"</span> <span class="p">{</span>
  <span class="n">value</span> <span class="o">=</span> <span class="s2">"${aws_instance.example.public_dns}"</span>
<span class="p">}</span>
</code></pre></div>          Ok! Now we're ready to finally create some Test Kitchen instances!
          <br><br>
          Go ahead and run:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>bundle <span class="nb">exec </span>kitchen converge
</code></pre></div>          NOTE: If you receive the error "Error launching source instance: VPCResourceNotSpecified: The specified instance type can only be used in a VPC", check out the EC2 t2 Instance Type Requirement document.
          <br><br>
          And it should converge successfully and you should see output that includes:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>Outputs:

public_dns <span class="o">=</span> your_aws_instance_public_ip
</code></pre></div>          Let's first try running the tests as is - even though we haven't written any yet.
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>bundle <span class="nb">exec </span>kitchen verify
</code></pre></div>          And if it runs successfully, you should see output that includes:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>Finished <span class="k">in </span>0.002 seconds <span class="o">(</span>files took 2.54 seconds to load<span class="o">)</span>
0 examples, 0 failures
</code></pre></div>          Let's add some tests!
          <br><br>
          Open up the file
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>vim <span class="nb">test</span>/integration/default/controls/operating_system_spec.rb
</code></pre></div>          And let's add in a very basic test to make sure we are running on an Ubuntu system.
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>control <span class="s1">'operating_system'</span> <span class="k">do
  </span>describe <span class="nb">command</span><span class="o">(</span><span class="s1">'lsb_release -a'</span><span class="o">)</span> <span class="k">do
    </span>its<span class="o">(</span><span class="s1">'stdout'</span><span class="o">)</span> <span class="o">{</span> should match <span class="o">(</span>/Ubuntu/<span class="o">)</span> <span class="o">}</span>
  end
end
</code></pre></div>          Now save and close the file and run the test.
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>bundle <span class="nb">exec </span>kitchen verify
</code></pre></div>          And hey, it passed! You should see output that includes:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>Command: <span class="sb">`</span>lsb_release <span class="nt">-a</span><span class="sb">`</span>
  stdout
    is expected to match /Ubuntu/

Finished <span class="k">in </span>0.23381 seconds <span class="o">(</span>files took 2.62 seconds to load<span class="o">)</span>
1 example, 0 failures
</code></pre></div>          It's nice that it passed...but we still need to make sure that it fails to be certain it tests what we think it tests. Let's try changing our Terraform config to spin up an Amazon Linux System, rather than an Ubuntu system, and make sure that this test fails.
          <br><br>
          Go ahead and destroy your current test kitchen instances with:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>bundle <span class="nb">exec </span>kitchen destroy
</code></pre></div>          Open up your variables file
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>vim testing.tfvars
</code></pre></div>          And change this content:
          <br><br>
<div class="highlight"><pre class="syntax-highlight ruby"><code><span class="n">region</span> <span class="o">=</span> <span class="s2">"us-east-1"</span>
<span class="n">instance_type</span> <span class="o">=</span> <span class="s2">"m3.medium"</span>
<span class="n">ami</span> <span class="o">=</span> <span class="s2">"ami-fce3c696"</span>
</code></pre></div>          To this content (we are changing our AMI type to be an Amazon Linux AMI within the us-east-1 AWS region.
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>region <span class="o">=</span> <span class="s2">"us-east-1"</span>
instance_type <span class="o">=</span> <span class="s2">"m3.medium"</span>
ami <span class="o">=</span> <span class="s2">"ami-6869aa05"</span>
</code></pre></div>          Now create your test kitchen instance:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>bundle <span class="nb">exec </span>kitchen converge
</code></pre></div>          Now run the tests:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>bundle <span class="nb">exec </span>kitchen verify
</code></pre></div>          Whoops! Looks like we got an error this run!
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code><span class="o">&gt;&gt;&gt;&gt;&gt;&gt;</span> <span class="nt">------Exception-------</span>
<span class="o">&gt;&gt;&gt;&gt;&gt;&gt;</span> Class: Kitchen::ActionFailed
<span class="o">&gt;&gt;&gt;&gt;&gt;&gt;</span> Message: 1 actions failed.
<span class="o">&gt;&gt;&gt;&gt;&gt;&gt;</span>     Verify failed on instance &lt;default-ubuntu&gt;.  Please see
.kitchen/logs/default-ubuntu.log <span class="k">for </span>more details
</code></pre></div>          So let's take a look at the <p class="font-weight-bold" style="color: #32c850; display: inline;">.kitchen/log/default-ubuntu.log</p> Parsing through the output, we see this:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>ERROR <span class="nt">--</span> default-ubuntu: Message: Transport error, can<span class="s1">'t connect to
'</span>ssh<span class="s1">' backend: SSH session could not be established
</span></code></pre></div>          This is because of the verifier in our <p class="font-weight-bold" style="color: #32c850; display: inline;">.kitchen.yml</p>
          <br><br>
<div class="highlight"><pre class="syntax-highlight yaml"><code><span class="na">verifier</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>
  <span class="na">systems</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">default</span>
      <span class="na">controls</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">operating_system</span>
      <span class="na">hostnames</span><span class="pi">:</span> <span class="s">public_dns</span>
      <span class="na">username</span><span class="pi">:</span> <span class="s">ubuntu</span>
      <span class="na">reporter</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">documentation</span>
</code></pre></div>          Notice that the username we have specified for our test is ubuntu - this is fine for an ubuntu instance, but for an Amazon Linux instance, we need to use the ec2-user username
          <br><br>
          So let's go ahead and change that, the verifier section of your <p class="font-weight-bold" style="color: #32c850; display: inline;">.kitchen.yml</p> should now look like this:
          <br><br>
<div class="highlight"><pre class="syntax-highlight yaml"><code><span class="na">verifier</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>
  <span class="na">systems</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">default</span>
      <span class="na">controls</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">operating_system</span>
      <span class="na">backend</span><span class="pi">:</span> <span class="s">ssh</span>
      <span class="na">key_files</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">~/.ssh/ncs-laptop.pem</span>
      <span class="na">hosts_output</span><span class="pi">:</span> <span class="s">public_dns</span>
      <span class="na">user</span><span class="pi">:</span> <span class="s">ec2-user</span>
      <span class="na">reporter</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">documentation</span>
</code></pre></div>          Now try running the tests again:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>bundle <span class="nb">exec </span>kitchen verify
</code></pre></div>          And now we see a test failure:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>Command: <span class="sb">`</span>lsb_release <span class="nt">-a</span><span class="sb">`</span>
  stdout
    is expected to match /Ubuntu/ <span class="o">(</span>FAILED - 1<span class="o">)</span>

Failures:

  1<span class="o">)</span> Command: <span class="sb">`</span>lsb_release <span class="nt">-a</span><span class="sb">`</span> stdout is expected to match /Ubuntu/
     Failure/Error: DEFAULT_FAILURE_NOTIFIER <span class="o">=</span> lambda <span class="o">{</span> |failure, _opts| raise failure <span class="o">}</span>

       expected <span class="s2">""</span> to match /Ubuntu/
       Diff:
       @@ <span class="nt">-1</span>,2 +1,2 @@
       -/Ubuntu/
       +<span class="s2">""</span>
     <span class="c"># ./test/integration/default/controls/operating_system_spec.rb:3:in `block (3 levels) in load_with_context'</span>

Finished <span class="k">in </span>0.26506 seconds <span class="o">(</span>files took 5.52 seconds to load<span class="o">)</span>
1 example, 1 failure

Failed examples:

rspec  <span class="c"># Command: `lsb_release -a` stdout is expected to match /Ubuntu/</span>
</code></pre></div>          Alright, that means our test is failing when it is supposed to be failing, and passing when it is supposed to pass.
          <br><br>
          Open up your <p class="font-weight-bold" style="color: #32c850; display: inline;">.kitchen.yml</p> file and change the username back to ubuntu
          <br><br>
<div class="highlight"><pre class="syntax-highlight yaml"><code><span class="na">verifier</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">terraform</span>
  <span class="na">systems</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">default</span>
      <span class="na">controls</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">operating_system</span>
      <span class="na">backend</span><span class="pi">:</span> <span class="s">ssh</span>
      <span class="na">key_files</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">~/.ssh/ncs-laptop.pem</span>
      <span class="na">hosts_output</span><span class="pi">:</span> <span class="s">public_dns</span>
      <span class="na">user</span><span class="pi">:</span> <span class="s">ec2-user</span>
      <span class="na">reporter</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">documentation</span>
</code></pre></div>          And open up your <p class="font-weight-bold" style="color: #32c850; display: inline;">testing.tfvars</p> file and switch back to an Ubuntu AMI
          <br><br>
<div class="highlight"><pre class="syntax-highlight ruby"><code><span class="n">region</span> <span class="o">=</span> <span class="s2">"us-east-1"</span>
<span class="n">instance_type</span> <span class="o">=</span> <span class="s2">"m3.medium"</span>
<span class="n">ami</span> <span class="o">=</span> <span class="s2">"ami-fce3c696"</span>
</code></pre></div>          Then destroy your current kitchen instances:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>bundle <span class="nb">exec </span>kitchen destroy
</code></pre></div>          Then converge again:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>bundle <span class="nb">exec </span>kitchen converge
</code></pre></div>          And then run verify one more time, now you should see everything pass:
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>bundle <span class="nb">exec </span>kitchen verify
</code></pre></div>          Huzzah! This concludes our Terraform AWS Provider walk-through tutorial.
          <br><br>
          Now, make sure to destroy your test instances
          <br><br>
<div class="highlight"><pre class="syntax-highlight shell"><code>bundle <span class="nb">exec </span>kitchen destroy
</code></pre></div>        </div>
      </div>
    </div>
  </div>
</div>

    </div>
    <footer class="footer">
      <div class="container">
        <span class="text-muted">Community driven, created and maintained by
          <a href="http://copado.com" style="color: #32c850;">
            <img src="/kitchen-terraform/images/copado_logo.png" class="d-inline-block" style="vertical-align: sub;" width="30" height="24" alt="Copado NCS LLC logo" />
            Copado NCS LLC
          </a>
        </span>
      </div>
    </footer>
  </body>
</html>
